package net.sxnic.workflow.pd.utils;

import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.sxnic.comm.coe.Coe;
import net.sxnic.workflow.handler.Handler;
import net.sxnic.workflow.node.Node;
import net.sxnic.workflow.node.NodeManager;
import net.sxnic.workflow.pd.Pd;
import net.sxnic.workflow.pd.PdManager;
import net.sxnic.workflow.transition.Transition;
import net.sxnic.workflow.transition.TransitionManager;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PdUtils {

	private static Logger logger = LoggerFactory.getLogger(PdUtils.class);

	public static void readxml(File file, PdManager pdManager,
			NodeManager nodeManager,TransitionManager trsManger) throws Exception {

		SAXReader saxReader = new SAXReader();
		Document doc = saxReader.read(file);

		logger.debug("read xml file success! file :" + file.getAbsolutePath());

		String processName;
		String nodeName;
		String nodeCate;

		String handlerClass;
		String handlerAction;

		Handler handler;

		String epName;
		String epValue;

		boolean hasStartNode = false;
		boolean hasEndNode = false;

		Coe coe;

		Element root = doc.getRootElement();

		List processList = root.elements();

		Iterator iter = processList.iterator();
		// 循环流程定义PD process
		while (iter.hasNext()) {
			Element e = (Element) iter.next();
			processName = e.getName();

			// 创建一个pd
			Pd pd = new Pd();
			pd.setName(processName);
			Pd exist_last_pd = pdManager.findLatestPdByName(pd.getName());
			int pd_version = 0;
			if (exist_last_pd == null) {
				pd_version = 0;
			} else {
				pd_version = exist_last_pd.getPdVersion();
			}
			pd.setPdVersion(pd_version + 1);

			pdManager.save(pd);
			logger.debug("====pd===" + pd.getName());

			// pd级别的 handlers
			List<Element> nodeList = doc.selectNodes("/root/" + processName
					+ "/node");
			Iterator nodeIterator = nodeList.iterator();
			
			Transition trs = null;

			// 循环node定义
			while (nodeIterator.hasNext()) {
				Element eNode = (Element) nodeIterator.next();
				nodeName = eNode.attributeValue("name");
				nodeCate = eNode.attributeValue("cate");

				if (StringUtils.isBlank(nodeName)) {
					throw new Exception("node节点必须有name属性");
				}

				logger.debug("===node====" + nodeName);
				Node node = new Node();
				node.setName(nodeName);

				if (StringUtils.isNotBlank(nodeCate)) {
					node.setCate(nodeCate);
				}

				node.setPd(pd);
				nodeManager.save(node);
				logger.debug("===save node success===" + nodeName);

				List<Element> proList = eNode.elements();

				// 循环node的属性定义
				for (Element ep : proList) {
					epName = ep.getName();
					logger.debug("===node's=properties====" + epName);
					if ("handler".equals(epName)) {
						handlerClass = ep.attributeValue("class");
						handlerAction = ep.attributeValue("action");

						if (StringUtils.isBlank(handlerAction)
								|| StringUtils.isBlank(handlerClass)) {
							throw new Exception("handler的class属性和action属性必须有");
						}

						handler = new Handler();
						handler.setAction(handlerAction);
						handler.setClassName(handlerClass);
						logger.debug("===node handler=====" + handlerClass);
						node.getHandlers().add(handler);
					} else if ("nextNode".equals(epName)) {
						node.setNextNode(ep.getText());
					} else if ("jsp".equals(epName)) {
						node.setJsp(ep.getText());
					} else if ("chart".equals(epName)) {
						node.setChart(ep.getText());
					} else if ("wfChartNextNode".equals(epName)) {
						node.setWfChartNextNode(ep.getText());
					} else if ("statusCode".equals(epName)) {
						node.setStatusCode(ep.getText());
					} else if ("validate".equals(epName)) {
						node.setValidate(ep.getText());
					} else if ("buttons".equals(epName)) {
						node.setButtons(ep.getText());
					} else if ("assignee".equals(epName)) {
						node.setAssignee(ep.getText());
					} else if ("alias".equals(epName)) {
						node.setAlias(ep.getText());
					} else if ("statusName".equals(epName)) {
						node.setStatusName(ep.getText());
					} else {
						epValue = ep.getText();
						coe = new Coe(epName, epValue);
						node.getCoes().add(coe);
						logger.debug("ep===" + epName + "====" + epValue);
					}
				}
				
				nodeManager.update(node);
				logger.debug("===updte node success=====");
			}
		}
		
		//重建Transition
		createTransition(file, pdManager, nodeManager, trsManger);

	}
	
	
	public static void createTransition(File file, PdManager pdManager,
			NodeManager nodeManager,TransitionManager trsManger) throws Exception{
		SAXReader saxReader = new SAXReader();
		Document doc = saxReader.read(file);

		logger.debug("read xml file success! file :" + file.getAbsolutePath());

		String processName;
		String nodeName;		

		Element root = doc.getRootElement();

		List processList = root.elements();

		Iterator iter = processList.iterator();
		// 循环流程定义PD process
		while (iter.hasNext()) {
			Element e = (Element) iter.next();
			processName = e.getName();
			
			Pd pd = pdManager.findLatestPdByName(processName);			

			// pd级别的 handlers
			List<Element> nodeList = doc.selectNodes("/root/" + processName
					+ "/node");
			Iterator nodeIterator = nodeList.iterator();
			
			Transition trs = null;

			// 循环node定义
			while (nodeIterator.hasNext()) {
				Element eNode = (Element) nodeIterator.next();
				nodeName = eNode.attributeValue("name");
				
				List<Element> proList = eNode.selectNodes("transition");
				Node node = nodeManager.findByPdName(pd, nodeName);
				node.getTransitions().clear();
				// 循环node的属性定义
				for (Element ep : proList) {
						//后续节点
						trs = trsManger.save(ep.attributeValue("name"), node.getName(), ep.attributeValue("to"),pd);
						node.getTransitions().add(trs);
						logger.debug("===node:{} add transition:{}==success===",node.getName(),trs.getName());
					
				}
				
				nodeManager.update(node);	
			}
		}
		
		logger.debug("===重建Transition与Node关系完成=====");
	}

	public static void validatexml(File file) throws Exception {

		SAXReader saxReader = new SAXReader();
		Document doc = saxReader.read(file);

		logger.debug("read xml file success! file :" + file.getAbsolutePath());

		String processName;
		String nodeName;
		String nodeCate;

		String handlerClass;
		String handlerAction;

		Handler handler;

		String epName;
		String epValue;

		boolean hasStartNode = false;
		boolean hasEndNode = false;

		Set<String> pdNames = new HashSet<String>();
		Set<String> nodeNames = new HashSet<String>();

		Coe coe;

		Element root = doc.getRootElement();

		List processList = root.elements();

		Iterator iter = processList.iterator();
		// 循环流程定义PD process
		while (iter.hasNext()) {
			Element e = (Element) iter.next();
			processName = e.getName();

			// 创建一个pd
			Pd pd = new Pd();
			pd.setName(processName);

			pdNames = validatePd(pd, pdNames);

			logger.debug("====pd===" + pd.getName());

			// pd级别的 handlers
			List<Element> nodeList = doc.selectNodes("/root/" + processName
					+ "/node");
			Iterator nodeIterator = nodeList.iterator();

			hasStartNode = false;
			hasEndNode = false;
			logger.debug(pd.getName() + "==clear befor===" + nodeNames.size());
			nodeNames.clear();
			logger.debug("==clear after===" + nodeNames.size());

			// 循环node定义
			while (nodeIterator.hasNext()) {
				Element eNode = (Element) nodeIterator.next();
				nodeName = eNode.attributeValue("name");
				nodeCate = eNode.attributeValue("cate");

				if (StringUtils.isBlank(nodeName)) {
					throw new Exception("node节点必须有name属性");
				}

				if ("start".equals(nodeCate)) {
					hasStartNode = true;
				}

				if ("end".equals(nodeCate)) {
					hasEndNode = true;
				}

				Node node = new Node();
				node.setName(nodeName);

				if (StringUtils.isNotBlank(nodeCate)) {
					node.setCate(nodeCate);
				}

				node.setPd(pd);

				List<Element> proList = eNode.elements();

				// 循环node的属性定义
				for (Element ep : proList) {
					epName = ep.getName();
					logger.debug("===node's=properties====" + epName);
					if ("handler".equals(epName)) {
						handlerClass = ep.attributeValue("class");
						handlerAction = ep.attributeValue("action");

						if (StringUtils.isBlank(handlerAction)
								|| StringUtils.isBlank(handlerClass)) {
							throw new Exception("handler的class属性和action属性必须有");
						}

						handler = new Handler();
						handler.setAction(handlerAction);
						handler.setClassName(handlerClass);
						node.getHandlers().add(handler);
					} else if ("nextNode".equals(epName)) {
						node.setNextNode(ep.getText());
					} else if ("jsp".equals(epName)) {
						node.setJsp(ep.getText());
					} else if ("chart".equals(epName)) {
						node.setChart(ep.getText());
					} else if ("wfChartNextNode".equals(epName)) {
						node.setWfChartNextNode(ep.getText());
					} else if ("autoTask".equals(epName)) {
						//node.setAutoTask(ep.getText());
					} else if ("validate".equals(epName)) {
						node.setValidate(ep.getText());
					} else {
						epValue = ep.getText();
						coe = new Coe(epName, epValue);
						node.getCoes().add(coe);
					}

				}

				validateNode(node, nodeNames);
			}
			if (!hasStartNode) {
				throw new Exception("===pd has no startNode===" + pd.getName());
			}

			if (!hasEndNode) {
				throw new Exception("===pd has no endNode===" + pd.getName());
			}
		}

	}

	public static Set<String> validatePd(Pd pd, Set<String> pdNames)
			throws Exception {
		if (StringUtils.isBlank(pd.getName())) {
			throw new Exception("pd name is null");
		}

		if (pdNames.contains(pd.getName())) {
			throw new Exception("pd name redefined++" + pd.getName());
		} else {
			pdNames.add(pd.getName());
		}

		return pdNames;
	}

	public static Set<String> validateNode(Node node, Set<String> nodeNames)
			throws Exception {
		// 验证name
		if (StringUtils.isBlank(node.getName())) {
			throw new Exception("node name is null");
		}

		if (nodeNames.contains(node.getName())) {
			throw new Exception("node name redefined===nodeName==="
					+ node.getName() + "===pdname===" + node.getPd().getName());
		} else {
			nodeNames.add(node.getName());
		}

		return nodeNames;
	}

}
